# -*- coding:utf-8 -*-

import os
import sys
import ConfigParser

from ConfigInfo import Profile
from ConfigInfo import RuleInfo
from ConfigInfo import FTPInfo
from ConfigInfo import PathInfo
from ConfigInfo import Rename
from ConfigInfo import OverStock
from ConfigInfo import StatLog
from ConfigInfo import AppConf
from MyException import ReadConfError

from MyPrint import print_red_line


#定义配置文件读取类
class ConfigReader:
    def __init__(self):
        """
        初始化
        """
        self.profile_file = "./pre.conf"
        self.app_conf_dir = "../etc/Config.d"
        
    def set_profile_file(self, profile_file):
        """
        设置私有配置文件路径
        @param profile_path: 私有配置文件路径
        """
        self.profile_file = profile_file
    
    def set_app_conf_dir(self, app_conf_dir):
        """
        设置应用配置文件目录
        @param app_conf_dir: 应用配置文件目录
        """
        self.app_conf_dir = app_conf_dir
        
    def get_profile_file(self):
        """
        获取私有配置文件路径
        @return: 私有配置文件路径
        """
        return self.profile_file
    
    def get_app_conf_dir(self):
        """
        获取应用配置文件目录
        @return: 应用配置文件目录
        """
        return self.app_conf_dir
    
    def read_profile(self):
        """
        读取私有配置文件
        @return: 私有配置文件实例
        """
        try:
            #声明私有配置文件实例
            profile = Profile()
            cf = ConfigParser.ConfigParser()
            cf.read(self.profile_file)
            
            #读取RECV节点
            profile.recv_keyword = cf.get("RECV", "Keyword_Recv_Dir")
            profile.recv_keyword_max_time = cf.getint("RECV", "Keyword_Recv_Max_Time")
            profile.recv_keyword_max_size = cf.getint("RECV", "Keyword_Recv_Max_Size")
            profile.recv_keyword_thr_num = cf.getint("RECV", "Keyword_Recv_Thread_Num")
            profile.recv_keyword_enable = cf.getint("RECV", "Keyword_Recv_Enable")

            profile.recv_mass = cf.get("RECV", "Mass_Recv_Dir")
            profile.recv_mass_max_time = cf.getint("RECV", "Mass_Recv_Max_Time")
            profile.recv_mass_max_size = cf.getint("RECV", "Mass_Recv_Max_Size")
            profile.recv_mass_thr_num = cf.getint("RECV", "Mass_Recv_Thread_Num")
            profile.recv_mass_enable = cf.getint("RECV", "Mass_Recv_Enable")

            profile.recv_bigdata = cf.get("RECV", "Bigdata_Recv_Dir")
            profile.recv_bigdata_max_time = cf.getint("RECV", "Bigdata_Recv_Max_Time")
            profile.recv_bigdata_max_size = cf.getint("RECV", "Bigdata_Recv_Max_Size")
            profile.recv_bigdata_thr_num = cf.getint("RECV", "Bigdata_Recv_Thread_Num")
            profile.recv_bigdata_enable = cf.getint("RECV", "Bigdata_Recv_Enable")

            profile.recv_zip = cf.get("RECV", "Zip_Recv_Dir")
            profile.recv_zip_thr_num = cf.getint("RECV", "Zip_Recv_Thread_Num")

            # 读物SEND节点
            profile.send_keyword = cf.get("SEND", "Keyword_Send_Dir")
            profile.send_keyword_tmp = cf.get("SEND", "Keyword_Send_Dir_Tmp")
            profile.send_mass = cf.get("SEND", "Mass_Send_Dir")
            profile.send_mass_tmp = cf.get("SEND", "Mass_Send_Dir_Tmp")
            profile.send_bigdata = cf.get("SEND", "Bigdata_Send_Dir")
            profile.send_bigdata_tmp = cf.get("SEND", "Bigdata_Send_Dir_Tmp")
            profile.send_zip = cf.get("SEND", "Zip_Send_Dir")
            profile.send_zip_tmp = cf.get("SEND", "Zip_Send_Dir_Tmp")
            profile.unzip_bigdata_start = cf.get("SEND", "Bigdata_Start_Time")
            profile.unzip_bigdata_end = cf.get("SEND", "Bigdata_End_Time")

            #读取CACHE节点
            profile.cache_dir = cf.get("CACHE", "Cache_Dir")

            #读取BACKUP节点
            profile.backup_dir = cf.get("BACKUP", "Backup_Dir")

            #读取LOG节点
            profile.time_rotate_backup_num = cf.getint("LOG", "TIME_ROTATE_BACKUP_NUM")
            profile.size_rotate_backup_num = cf.getint("LOG", "SIZE_ROTATE_BACKUP_NUM")
            profile.log_dir = cf.get("LOG", "Log_Dir")
            profile.log_lev = cf.get("LOG", "Log_Level")
            
            return profile
        except Exception, msg:
            raise ReadConfError(msg)
    
    def read_all_app_conf(self):
        """
        读取所有应用配置文件
        @return: 所有应用配置文件实例
        """
        #声明应用配置文件
        all_app_conf = AppConf()
        
        #获取应用配置文件目录下所有文件
        file_list = os.listdir(self.app_conf_dir)
        
        for filename in file_list:
            #检查应用配置文件名
            if not filename.endswith(".conf"):
                continue
            #读取应用配置文件
            file_path = os.path.join(self.app_conf_dir, filename)
            
            #读取应用配置文件异常处理
            try:
                tmp_app_conf = self.read_app_conf(file_path)
            except ReadConfError, msg:
                continue
              
            #合并匹配规则
            all_app_conf.match_rule_list.extend(tmp_app_conf.match_rule_list)
            all_app_conf.nomatch_rule_list.extend(tmp_app_conf.nomatch_rule_list)
                
            #合并FTP模块
            all_app_conf.ftp_unit_list.extend(tmp_app_conf.ftp_unit_list)
                
            #合并本地目录
            all_app_conf.path_unit_list.extend(tmp_app_conf.path_unit_list)
            
            #合并高级应用
            all_app_conf.adv_conf_list.extend(tmp_app_conf.adv_conf_list)
        
        return all_app_conf
    
    def read_app_conf(self, file_path):
        """
        读取一个应用配置文件
        @param filename: 应用配置文件路径
        @return: 应用配置文件数据结构实例
        """
        try:
            app_conf = AppConf()
            cf = ConfigParser.ConfigParser()
            cf.read(file_path)
            tmp_section_list = cf.sections()
            
            #读取规则
            for option in cf.options("RULE"):
                #申明一般匹配规则
                match_rule_info = RuleInfo()
                match_rule_info.rule = option
                #声明否定匹配规则
                nomatch_rule_info = RuleInfo()
                nomatch_rule_info.rule = option
                #分析发送接口
                tmp_send_unit = cf.get("RULE", option)
                for send_unit_name in [send_unit.replace(" ", "") for send_unit in tmp_send_unit.split(",") if send_unit]:
                    if (send_unit_name.startswith("FTP_")) and (send_unit_name in tmp_section_list):
                        global_name = self.get_global_name(file_path, send_unit_name)
                        if not global_name in match_rule_info.ftp_list:
                            match_rule_info.ftp_list.append(global_name)
                    elif send_unit_name.startswith("PATH_") and (send_unit_name in tmp_section_list):
                        global_name = self.get_global_name(file_path, send_unit_name)
                        if not global_name in match_rule_info.path_list:
                            match_rule_info.path_list.append(global_name)
                    elif send_unit_name.startswith("-FTP_") and (send_unit_name[1:] in tmp_section_list):
                        global_name = self.get_global_name(file_path, send_unit_name[1:])
                        if not global_name in nomatch_rule_info.ftp_list:
                            nomatch_rule_info.ftp_list.append(global_name)
                    elif send_unit_name.startswith("-PATH_") and (send_unit_name[1:] in tmp_section_list):
                        global_name = self.get_global_name(file_path, send_unit_name[1:])
                        if not global_name in nomatch_rule_info.path_list:
                            nomatch_rule_info.path_list.append(global_name)
                    else:
                        pass
                #添加匹配规则
                if match_rule_info.ftp_list or match_rule_info.path_list:
                    app_conf.match_rule_list.append(match_rule_info)
                if nomatch_rule_info.ftp_list or nomatch_rule_info.path_list:
                    app_conf.nomatch_rule_list.append(nomatch_rule_info)
                
            #读取FTP模块配置和本地目录配置
            for section in tmp_section_list:
                if section.startswith("FTP_"):    
                    ftp_info = FTPInfo()
                    ftp_info.name = self.get_global_name(file_path, section)
                    tmp_ip = cf.get(section, "SERVER_IP")
                    ftp_info.ip_list = [ip.strip() for ip in tmp_ip.split(",") if ip]
                    ftp_info.port = cf.getint(section, "SERVER_PORT")
                    ftp_info.username = cf.get(section, "SERVER_USERNAME")
                    ftp_info.password = cf.get(section, "SERVER_PASSWORD")
                    ftp_info.tmp_dir = cf.get(section, "SERVER_TMP")
                    ftp_info.dst_dir = cf.get(section, "SERVER_DST")
                    if cf.has_option(section, "ADVANCED_CONF"):
                        tmp_adv_conf = cf.get(section, "ADVANCED_CONF")
                        for app_name in tmp_adv_conf.split(","):
                            app_name = app_name.strip()
                            if not app_name: continue
                            if app_name in tmp_section_list:
                                ftp_info.adv_conf.append(self.get_global_name(file_path, app_name))
                    app_conf.ftp_unit_list.append(ftp_info)
                elif section.startswith("PATH_"):
                    path_info = PathInfo()
                    path_info.name = self.get_global_name(file_path, section)
                    path_info.tmp_dir = cf.get(section, "TMP_DIR")
                    path_info.dst_dir = cf.get(section, "DST_DIR")
                    if cf.has_option(section, "ADVANCED_CONF"):
                        tmp_adv_conf = cf.get(section, "ADVANCED_CONF")
                        for app_name in tmp_adv_conf.split(","):
                            app_name = app_name.strip()
                            if not app_name: continue
                            if app_name in tmp_section_list:
                                path_info.adv_conf.append(self.get_global_name(file_path, app_name))                
                    app_conf.path_unit_list.append(path_info)
                elif section.startswith("RENAME_"):
                    rename = Rename()
                    rename.app_name = self.get_global_name(file_path, section)
                    rename.old_keyword = cf.get(section, "OLD_KEYWORD")
                    rename.new_keyword = cf.get(section, "NEW_KEYWORD")
                    app_conf.adv_conf_list.append(rename)
                elif section.startswith("OVERSTOCK_"):
                    overstock = OverStock()
                    overstock.app_name = self.get_global_name(file_path, section)
                    overstock.max_file_num = cf.getint(section, "MAX_FILE_NUM")
                    overstock.max_node_num = cf.getint(section, "MAX_NODE_NUM")
                    overstock.max_over_num = cf.getint(section, "MAX_OVER_NUM")
                    app_conf.adv_conf_list.append(overstock)
                elif section.startswith("STATLOG_"):
                    statlog = StatLog()
                    statlog.app_name = self.get_global_name(file_path, section)
                    statlog.data_dest = cf.get(section, "DATA_DEST")
                    app_conf.adv_conf_list.append(statlog)
                else:
                    pass
            return app_conf
        except Exception, msg:
            raise ReadConfError(msg)

    def get_global_name(self, filename, section):
        """
        生成全局模块名称
        @param filename: 应用配置文件名
        @param ftpname: 配置节点名
        @return: 配置节点全局名称
        """
        return os.path.basename(filename)[:-5] + "_" + section

#单元测试
import unittest
    
class ConfigTestCase(unittest.TestCase):
    def setUp(self):
        self.config = Config()
    
    def tearDown(self):
        pass
    
    def testReadProfile(self):
        profile = self.config.read_profile()
        profile.show()
        
    def testReadAllAppConf(self):
        app_conf = self.config.read_all_app_conf()
        app_conf.show()
        
if __name__ == "__main__":
    suite = unittest.TestSuite()
    suite.addTest(ConfigTestCase("testReadProfile"))
    suite.addTest(ConfigTestCase("testReadAllAppConf"))
    
    runner = unittest.TextTestRunner()
    runner.run(suite)
    
